Data Story: Het verband tussen de levenstandaarden in een land en migratie#

  1. Lars van der Groep 14346168

  2. Guido Elzer 15817628

  3. Simon van Rooij 15692221

Inleiding#

Migratie is al erg lang een erg belangrijk onderwerp waar de meningen verdeeld over zijn. Er zijn namelijk verschillende redenen waardoor mensen uit hun herkomst land vertrekken. Veel mensen en ook overheden zijn geen voorstander van buitenlanders die binnenkomen in hun land, omdat ze gebruik willen maken van het succes dat daar behaald is. In deze datastory wordt er onderzocht of mensen vooral emigreren om uit hun eigen land weg te gaan, om naar een beter land te gaan, of misschien wel een combinatie tussen de twee.

Eerste perspectief:#

Migranten emigreren vooral uit hun eigen land omdat de levensomstandigheden in hun eigen land te slecht/gevaarlijk zijn om een normaal leven in te kunnen hebben.

Argument 1: Landen met een historische gebeurtenis wat de leefomstandigheden onleefbaar maakt hebben een sterke stijging van migratie als gevolg.#

Argument 2: Er is sprake van een zichtbaar verband tussen migratiecijfers een slechte leefomstandigheden maar een slechte leefomstandigheid heeft niet altijd een verhoging van migratie als gevolg.#

Tweede perspectief:#

Migratie heeft niet per se te maken met hoe slecht het met een land gaat maar eerder met hoe goed het met de buurlanden gaat.

Eerste argument: Mortality Rate en Migratie#

Tweede argument: gemiddeld BBP per persoon en emigratiepercentage trendline#

Derde argument: buurlandverschillen#

import pandas as pd
import plotly.express as px
import plotly.graph_objs as go
from plotly.offline import init_notebook_mode
from plotly.subplots import make_subplots
init_notebook_mode(connected=True)
from IPython.display import display, HTML
import json
import uuid

Dataset en Preprocessing#

Om onze argumenten te onderbouwen gebruiken we meerdere datasets die onze punten versterken. De dataset die centraal achter dit onderzoek staat is de dataset over wereldwijde migratie van de World Bank Group(2025) Deze dataset heeft meerdere variabelen die aangegeven zijn in de output hieronder. Alle jaartallen gebruiken data verzameld over een periode van 10 jaar. (Link naar de database https://databank.worldbank.org/source/global-bilateral-migration)

file = r"P_Data_Extract_From_Global_Bilateral_Migration.xlsx"
df = pd.read_excel(file)
df.head()
---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
File ~\miniconda3\envs\jupyterbook\lib\site-packages\pandas\compat\_optional.py:135, in import_optional_dependency(name, extra, errors, min_version)
    134 try:
--> 135     module = importlib.import_module(name)
    136 except ImportError:

File ~\miniconda3\envs\jupyterbook\lib\importlib\__init__.py:126, in import_module(name, package)
    125         level += 1
--> 126 return _bootstrap._gcd_import(name[level:], package, level)

File <frozen importlib._bootstrap>:1050, in _gcd_import(name, package, level)

File <frozen importlib._bootstrap>:1027, in _find_and_load(name, import_)

File <frozen importlib._bootstrap>:1004, in _find_and_load_unlocked(name, import_)

ModuleNotFoundError: No module named 'openpyxl'

During handling of the above exception, another exception occurred:

ImportError                               Traceback (most recent call last)
Cell In[2], line 2
      1 file = r"P_Data_Extract_From_Global_Bilateral_Migration.xlsx"
----> 2 df = pd.read_excel(file)
      3 df.head()

File ~\miniconda3\envs\jupyterbook\lib\site-packages\pandas\io\excel\_base.py:495, in read_excel(io, sheet_name, header, names, index_col, usecols, dtype, engine, converters, true_values, false_values, skiprows, nrows, na_values, keep_default_na, na_filter, verbose, parse_dates, date_parser, date_format, thousands, decimal, comment, skipfooter, storage_options, dtype_backend, engine_kwargs)
    493 if not isinstance(io, ExcelFile):
    494     should_close = True
--> 495     io = ExcelFile(
    496         io,
    497         storage_options=storage_options,
    498         engine=engine,
    499         engine_kwargs=engine_kwargs,
    500     )
    501 elif engine and engine != io.engine:
    502     raise ValueError(
    503         "Engine should not be specified when passing "
    504         "an ExcelFile - ExcelFile already has the engine set"
    505     )

File ~\miniconda3\envs\jupyterbook\lib\site-packages\pandas\io\excel\_base.py:1567, in ExcelFile.__init__(self, path_or_buffer, engine, storage_options, engine_kwargs)
   1564 self.engine = engine
   1565 self.storage_options = storage_options
-> 1567 self._reader = self._engines[engine](
   1568     self._io,
   1569     storage_options=storage_options,
   1570     engine_kwargs=engine_kwargs,
   1571 )

File ~\miniconda3\envs\jupyterbook\lib\site-packages\pandas\io\excel\_openpyxl.py:552, in OpenpyxlReader.__init__(self, filepath_or_buffer, storage_options, engine_kwargs)
    534 @doc(storage_options=_shared_docs["storage_options"])
    535 def __init__(
    536     self,
   (...)
    539     engine_kwargs: dict | None = None,
    540 ) -> None:
    541     """
    542     Reader using openpyxl engine.
    543 
   (...)
    550         Arbitrary keyword arguments passed to excel engine.
    551     """
--> 552     import_optional_dependency("openpyxl")
    553     super().__init__(
    554         filepath_or_buffer,
    555         storage_options=storage_options,
    556         engine_kwargs=engine_kwargs,
    557     )

File ~\miniconda3\envs\jupyterbook\lib\site-packages\pandas\compat\_optional.py:138, in import_optional_dependency(name, extra, errors, min_version)
    136 except ImportError:
    137     if errors == "raise":
--> 138         raise ImportError(msg)
    139     return None
    141 # Handle submodules: if we have submodule, grab parent module from sys.modules

ImportError: Missing optional dependency 'openpyxl'.  Use pip or conda to install openpyxl.

De tweede dataset die we gebruiken is de dataset over de ontwikkeling van landen over tijd aan de hand van levensstandaarden (world Bank Group, 2025). Het succes van een land is hier in veel verschillende methodes af te lezen. Door het grote aantal variabelen hebben we gekozen voor de meest belangrijke variabelen met de grootste hoeveelheid data. Door te kijken naar de stijgingen of dalingen in de dataset kunnen wij concluderen hoe een land zich over een periode van jaren/decennia ontwikkeld. (Link naar de database: https://databank.worldbank.org/source/world-development-indicators)

file2 = r"P_Data_Extract_From_World_Development_Indicators.xlsx"
df = pd.read_excel(file2)
df.head()
Country Name Country Code Series Name Series Code 1960 [YR1960] 1970 [YR1970] 1980 [YR1980] 1990 [YR1990] 2000 [YR2000]
0 Afghanistan AFG Access to clean fuels and technologies for coo... EG.CFT.ACCS.ZS .. .. .. .. 5.5
1 Afghanistan AFG Access to clean fuels and technologies for coo... EG.CFT.ACCS.RU.ZS .. .. .. .. 0.8
2 Afghanistan AFG Access to clean fuels and technologies for coo... EG.CFT.ACCS.UR.ZS .. .. .. .. 25.3
3 Afghanistan AFG Access to electricity (% of population) EG.ELC.ACCS.ZS .. .. .. .. 4.4
4 Afghanistan AFG Access to electricity, rural (% of rural popul... EG.ELC.ACCS.RU.ZS .. .. .. .. ..

De derde dataset die we gebruiken is de dataset met de inwonersaantallen per land. Aan de hand van deze dataset kunnen we de migratiecijfers vergelijken met de inwonersaantallen van het betreffende land. Dit heeft de voordelen dat inwoner aantallen niet een vertekend beeld geven in het onderzoek (Link naar de database: https://data.worldbank.org/indicator/SP.POP.TOTL)

De laatste datasets die gebruikt worden als ondersteuning van onze perspectieven zijn de datasets “bbb.xlsx, gdp_per_inwoner.xlsx en longitude-latitude.xlsx”. bbb.xlsx is een dataset die de sterftecijfers per land weergeeft over een tijdsperiode. Deze hebben we los gemaakt uit world development indicators.

gdp_per_inwoner.xlsx komt uit de World Bank Group (2025) en geeft het gemiddelde bruto binnenlands product (BBP/GDP) aan per inwoner over een tijdsperiode.

Longitude-latitude.xlsx is een dataset die uit Google Datasets(2025) komt. De dataset geeft de coördinaten van alle landen in de wereld aan.

We hebben onze datasets niet echt verwerkt voordat we gingen werken aan de visualisaties. We hebben dit bij elke visualisatie apart gedaan in plaats van in één keer aan het begin. Dit komt vooral omdat we allemaal appart de data hadden verwerkt voor onze eigen visualisaties.

import pandas as pd
import plotly.graph_objects as go


df = pd.read_excel('P_Data_Extract_From_Global_Bilateral_Migration.xlsx')
df.columns = df.columns.str.strip()
coords = pd.read_csv('longitude-latitude.csv')
coords = coords[['ISO-ALPHA-3', 'Latitude', 'Longitude']].rename(columns={'ISO-ALPHA-3': 'Code'}).drop_duplicates()


df = df.dropna(subset=['Country Origin Name', 'Country Origin Code'])
year_columns = [col for col in df.columns if '[' in col and ']' in col]

for year in year_columns:
    df[year] = pd.to_numeric(df[year], errors='coerce').fillna(0)

valid_countries = sorted(df['Country Origin Name'].unique())


fig = go.Figure()

default_country = valid_countries[0] if valid_countries else None
default_year = year_columns[0] if year_columns else None
default_year_str = default_year.split('[')[1].split(']')[0] if default_year else None


for country in valid_countries:
    for year_col in year_columns:
        year = year_col.split('[')[1].split(']')[0]

        country_df = df[df['Country Origin Name'] == country].copy()
        country_df = country_df.rename(columns={year_col: 'Migratie'})
        country_df = country_df.merge(coords, left_on='Country Origin Code', right_on='Code', how='left')
        country_df = country_df.rename(columns={'Latitude': 'Lat_O', 'Longitude': 'Lon_O'}).drop(columns='Code')
        country_df = country_df.merge(coords, left_on='Country Dest Code', right_on='Code', how='left')
        country_df = country_df.rename(columns={'Latitude': 'Lat_D', 'Longitude': 'Lon_D'}).drop(columns='Code')
        country_df = country_df.dropna(subset=['Lat_O', 'Lon_O', 'Lat_D', 'Lon_D'])

        lats, lons, names = [], [], []

        for _, row in country_df.iterrows():
            if float(row['Migratie']) > 0:
                lats.extend([row['Lat_O'], row['Lat_D'], None])
                lons.extend([row['Lon_O'], row['Lon_D'], None])
                names.extend([f"{row['Country Dest Name']} ({int(float(row['Migratie']))})"] * 2 + [None])

        fig.add_trace(
            go.Scattergeo(
                lat=lats,
                lon=lons,
                hovertext=names,
                mode='lines',
                line=dict(width=1, color='red'),
                name=f"{country} ({year})",
                visible=(country == default_country and year == default_year_str)
            )
        )


def make_visibility(selected_country, selected_year):
    visibility = []
    for trace in fig.data:
        trace_country = trace.name.split(' (')[0]
        trace_year = trace.name.split('(')[-1][:-1]
        visibility.append(trace_country == selected_country and trace_year == selected_year)
    return visibility


combo_buttons = []
for country in valid_countries:
    for year_col in year_columns:
        year = year_col.split('[')[1].split(']')[0]
        visibility = make_visibility(country, year)
        combo_buttons.append(
            dict(
                label=f"{country} - {year}",
                method="update",
                args=[
                    {"visible": visibility},
                    {"title": f"Migratiestromen vanuit {country} in {year}"}
                ]
            )
        )


fig.update_layout(
    title=f'Migratiestromen vanuit {default_country} in {default_year_str}',
    geo=dict(
        projection_type='natural earth',
        showland=True,
        landcolor='rgb(243, 243, 243)',
        countrycolor='rgb(204, 204, 204)',
        fitbounds="locations",
        lataxis_range=[-90, 90],
        lonaxis_range=[-180, 180]
    ),
    updatemenus=[
        dict(
            buttons=combo_buttons,
            direction="down",
            pad={"r": 10, "t": 10},
            showactive=True,
            x=0.1,
            xanchor="left",
            y=1.05,  
            yanchor="top"
        )
    ],
    height=700,
    margin=dict(r=0, t=80, l=0, b=0),
    dragmode=False  
)


fig.show(config={'scrollZoom': False, 'staticPlot': True})

Figuur 1: Een wereldwijde visualisatie van de emigratiestromen (rood) naar landen van bestemming vanuit een enkel land van oorsprong. Deze visualisatie geeft de lezer een inkijk in wereldwijde bewegingspatronen van migranten.

Perspectief 1#

Argument 1: Migratie en Leefomstandigheden, een Historische herhaling#

Wereldwijde migratie is vaak geen vrije keuze maar een beslissing genomen uit nood. Oorlog en landelijk conflict spelen daar vaak een rol bij, maar is dit ook werkelijk zo. Ons perspectief wat wij willen onderzoeken en beargumenten heeft te maken met migratie uit nood door slechte levensomstandigheden. Met het perspectief “Migranten emigreren vooral uit hun eigen land omdat de levensomstandigheden in hun eigen land te slecht/gevaarlijk zijn om een normaal leven in te kunnen hebben.” gaan we samen met de twee centrale datasets van dit onderzoek kijken naar een verband tussen migratie en levensstandaarden.

Een historisch voorbeeld wat ons perspectief zou moeten beargumenteren is bijvoorbeeld de Mexicaanse pesos crisis in 1994 wat voor een grote toename tot migratie bracht(Solano & Massey, 2022). Een indicator die de oorzaken van de crisis blootlegt is de explosieve groei van Mexico’s externe schulden. Deze indicator is tegen de migratiecijfers van Mexico aangelegd en is te zien in het resultaat in de figuur hieronder.

migratie = pd.read_excel("P_Data_Extract_From_Global_Bilateral_Migration.xlsx")
wb_data = pd.read_excel("P_Data_Extract_From_World_Development_Indicators.xlsx")

land = "Mexico"
indicator = "External debt stocks, total (DOD, current US$)"

jaar_kolommen = [col for col in migratie.columns if col.startswith('19') or col.startswith('20')]
jaar_kolommen = sorted(jaar_kolommen, key=lambda x: int(x.split()[0]))
migratie_uit_land = migratie[migratie["Country Origin Name"] == land].copy()
for col in jaar_kolommen:
    migratie_uit_land[col] = pd.to_numeric(migratie_uit_land[col], errors='coerce')

totaal_migratie = migratie_uit_land[jaar_kolommen].sum()
df_migratie = totaal_migratie.reset_index()
df_migratie.columns = ['Jaar', 'Migranten']
df_migratie['Jaar'] = df_migratie['Jaar'].str.extract(r'(\d{4})')[0]
wb_row = wb_data[(wb_data["Country Name"] == land) & 
                 (wb_data["Series Name"] == indicator)].copy()
wb_jaar_kolommen = [col for col in wb_row.columns if col.startswith('19') or col.startswith('20')]
for col in wb_jaar_kolommen:
    wb_row[col] = pd.to_numeric(wb_row[col], errors='coerce')

df_indicator = wb_row[wb_jaar_kolommen].T.reset_index()
df_indicator.columns = ['Jaar', indicator]
df_indicator['Jaar'] = df_indicator['Jaar'].str.extract(r'(\d{4})')[0]
merged = pd.merge(df_migratie, df_indicator, on='Jaar', how='inner')
fig = make_subplots(specs=[[{"secondary_y": True}]])

fig.add_trace(
    go.Bar(
        x=merged['Jaar'],
        y=merged['Migranten'],
        name="Migratie",
        marker_color='blue',
        hovertemplate="Jaar: %{x}<br>Migranten: %{y:,}"
    ),
    secondary_y=False
)

fig.add_trace(
    go.Scatter(
        x=merged['Jaar'],
        y=merged[indicator],
        name=indicator,
        line=dict(color="red", dash="dot"),
        hovertemplate=f"Jaar: %{{x}}<br>{indicator}: %{{y:,.0f}}"
    ),
    secondary_y=True
)

fig.update_layout(
    title=f"Emigratie vanuit {land} vs. {indicator} (Staaf + Lijn)",
    xaxis_title="Jaar",
    hovermode="x unified",
    legend=dict(orientation="h", yanchor="bottom", y=1.02),
    height=600
)

fig.update_yaxes(title_text="Migranten (aantal)", secondary_y=False)
fig.update_yaxes(title_text=indicator, secondary_y=True)

fig.show()

Figuur 2: De visualisatie van de vergelijking van migratiecijfers van Mexico (rood) en de schulden door de overheid in Amerikaanse Dollars (blauw). De schulden van de overheid liepen enorm op tijdens de crisis die Mexico onderging in het jaartal 1994. Deze visualisatie geeft de lezer inzicht in dat de migratie cijfers sterk stegen tussen 1990-2000 door een nationale crisis.

Uit de figuur is voor het land Mexico een duidelijke conclusie te trekken over de cijfers van migratie en de slechte levensomstandigheden van dus bijvoorbeeld een financiële crisis. Alhoewel deze argumentatie voor ons perspectief vrij duidelijk is, is het cruciaal om verder te kijken naar alle migratiecijfers van landen op de wereld en hun levensstandaarden.

Argument 2: Migratie en leefomstandigheden, landen met de meeste migratie#

Zoals eerder beargumenteerd is er sprake van migratie bij historische gebeurtenissen wat de leefomstandigheden van een land omlaag haalt, maar is er ook migratie als het land geen historische gebeurtenis ervaart maar gewoon een gemiddelde slechte leefomstandigheden heeft? Daarom zal er verder worden gekeken naar het verband van de levensstandaarden en de migratiecijfers van de top 20 landen met de meeste migratie over de tijdsperiode van onze datasets. De 20 landen die we gaan gebruiken voor verder onderzoek zijn hieronder in de figuur aangegeven.

%pip install xlrd #Deze dependency is nodig voor het runnen van de cell hieronder.
mig = pd.read_excel('P_Data_Extract_From_Global_Bilateral_Migration.xlsx')


pop = pd.read_excel('API_SP.POP.TOTL_DS2_en_excel_v2_124779.xlsx', skiprows=3)


pop.columns = pop.columns.map(str).str.strip()


years = ['1960 [1960]', '1970 [1970]', '1980 [1980]', '1990 [1990]', '2000 [2000]']


for year in years:
    mig[year] = pd.to_numeric(mig[year], errors='coerce')
    year_short = year.split()[0]
    if year_short in pop.columns:
        pop[year_short] = pd.to_numeric(pop[year_short], errors='coerce')


fig = go.Figure()
buttons = []

# Create one bar chart per year
for i, year in enumerate(years):
    year_short = year.split()[0]

    if year_short not in pop.columns:
        print(f"⚠️ Skipping {year_short} — not in population data.")
        continue


    mig_year = mig.groupby('Country Origin Name')[year].sum().reset_index()
    pop_year = pop[['Country Name', year_short]].copy()


    merged = pd.merge(mig_year, pop_year, left_on='Country Origin Name', right_on='Country Name', how='left')
    merged = merged.dropna()
    merged = merged[merged[year] > 0]


    merged = merged[merged[year_short] >= 1_000_000]


    merged['% Migrated'] = (merged[year] / merged[year_short]) * 100


    merged = merged[merged['% Migrated'] <= 100]
    
    # Get top 20 countries by % migrated
    top_20 = merged.nlargest(20, '% Migrated').sort_values('% Migrated', ascending=True)

    fig.add_trace(go.Bar(
        y=top_20['Country Name'],
        x=top_20['% Migrated'],
        orientation='h',
        text=top_20['% Migrated'].round(2).astype(str) + '%',
        textposition='auto',
        hoverinfo='text',
        hovertext=[
            f"<b>{row['Country Name']}</b><br>"
            f"Migrants: {row[year]:,}<br>"
            f"Population: {row[year_short]:,}<br>"
            f"% Migrated: {row['% Migrated']:.2f}%"
            for _, row in top_20.iterrows()
        ],
        visible=(i == 0),
        name=year_short,
        marker=dict(
            color=top_20['% Migrated'],
            colorscale='Viridis',
            cmin=0,
            cmax=merged['% Migrated'].quantile(0.95)
    )))


    visibility = [False] * len(years)
    visibility[i] = True
    buttons.append(dict(label=year_short, method='update',
                        args=[{'visible': visibility},
                              {'title': f'Top 20 Countries (>1M pop) by % Migrated ({year_short})'}]))

# Layout
fig.update_layout(
    updatemenus=[dict(
        buttons=buttons,
        direction='right',
        showactive=True,
        x=0.5,
        y=1.2,
        xanchor='center',
        yanchor='top'
    )],
    title='Top 20 Countries (>1M population) by % Population Migrated (1960)',
    xaxis_title='% of Population Migrated',
    yaxis_title='Country',
    height=700,
    margin=dict(l=150, r=50, b=100, t=100, pad=4),
    showlegend=False
)

fig.show()

Figuur 3: Een overzicht van de landen met de meeste migratie op basis van hoeveel procent van de bevolking geëmigreerd is.

Deze 20 landen hierboven aangegeven zullen we vergelijken met drie indicatoren die de ontwikkeling/levensstandaarden van een land kunnen schetsen.

Deze ontwikkeling zijn voornamelijk gefocust op de gezondheid van de burger en zijn als volgt:

“Survival to age 65, male (% of cohort)”, “Mortality rate, adult, female (per 1,000 female adults)”, “Life expectancy at birth, total (years)” Door deze indicatoren in kaart te brengen samen met de migratiecijfers van de landen kunnen we per land een conclusie trekken om vervolgens de eindconclusie over ons perspectief te beantwoorden.

import pandas as pd
from plotly.subplots import make_subplots
import plotly.graph_objects as go

migratie = pd.read_excel("P_Data_Extract_From_Global_Bilateral_Migration.xlsx")
wb_data = pd.read_excel("P_Data_Extract_From_World_Development_Indicators.xlsx")

landen = ["Puerto Rico", "Jamaica", "Albania", "West Bank and Gaza", "Bosnia and Herzegovina", "Ireland", "Georgia", "Armenia", "Trinidad and Tobago", "Moldova", "Kazakhstan", "Jordan", "Azerbaijan", "Kuwait", "Belarus", "Estonia", "Eritrea", "El Salvador", "Lebanon", "Lithuania"]
indicatoren = [
    "Survival to age 65, male (% of cohort)",
    "Mortality rate, adult, female (per 1,000 female adults)",
    "Life expectancy at birth, total (years)"
]

jaar_kolommen = [col for col in migratie.columns if col.startswith('19') or col.startswith('20')]
jaar_kolommen = sorted(jaar_kolommen, key=lambda x: int(x.split()[0]))

fig = make_subplots(specs=[[{"secondary_y": True}]])

traces = []
valid_countries = []

for land in landen:
    migratie_uit_land = migratie[migratie["Country Origin Name"] == land].copy()
    if migratie_uit_land.empty:
        continue
    for col in jaar_kolommen:
        migratie_uit_land[col] = pd.to_numeric(migratie_uit_land[col], errors='coerce')
    totaal_migratie = migratie_uit_land[jaar_kolommen].sum()
    df_migratie = totaal_migratie.reset_index()
    df_migratie.columns = ['Jaar', 'Migranten']
    df_migratie['Jaar'] = df_migratie['Jaar'].str.extract(r'(\d{4})')[0]
    indicator_dfs = []
    for indicator in indicatoren:
        wb_row = wb_data[(wb_data["Country Name"] == land) &
                         (wb_data["Series Name"] == indicator)].copy()
        if wb_row.empty:
            df_empty = pd.DataFrame({'Jaar': df_migratie['Jaar'], indicator: [None]*len(df_migratie)})
            indicator_dfs.append(df_empty)
            continue

        wb_jaar_kolommen = [col for col in wb_row.columns if col.startswith('19') or col.startswith('20')]
        for col in wb_jaar_kolommen:
            wb_row[col] = pd.to_numeric(wb_row[col], errors='coerce')

        df_indicator = wb_row[wb_jaar_kolommen].T.reset_index()
        df_indicator.columns = ['Jaar', indicator]
        df_indicator['Jaar'] = df_indicator['Jaar'].str.extract(r'(\d{4})')[0]
        indicator_dfs.append(df_indicator)


    from functools import reduce
    df_indicator_all = reduce(lambda left,right: pd.merge(left,right,on='Jaar', how='outer'), indicator_dfs)

    merged = pd.merge(df_migratie, df_indicator_all, on='Jaar', how='inner')

    if merged.empty:
        continue

    valid_countries.append(land)

    fig.add_trace(
        go.Scatter(
            x=merged['Jaar'],
            y=merged['Migranten'],
            name=f"Migratie - {land}",
            visible=False,
            hovertemplate="Jaar: %{x}<br>Migranten: %{y:,}",
            line=dict(width=2)
        ),
        secondary_y=False
    )
    traces.append(f"Migratie - {land}")

    for indicator in indicatoren:
        fig.add_trace(
            go.Scatter(
                x=merged['Jaar'],
                y=merged[indicator],
                name=f"{indicator} - {land}",
                visible=False,
                line=dict(dash="dot"),
                hovertemplate=f"Jaar: %{{x}}<br>{indicator}: %{{y:,.2f}}"
            ),
            secondary_y=True
        )
        traces.append(f"{indicator} - {land}")

dropdown_buttons = []

for land in valid_countries:

    visibility = []
    for trace_name in traces:
        if land in trace_name:
            visibility.append(True)
        else:
            visibility.append(False)
    dropdown_buttons.append(
        dict(
            label=land,
            method="update",
            args=[{"visible": visibility},
                  {"title": f"Migratie en indicatoren voor {land}"}]
        )
    )


fig.update_layout(
    title="Migratie en indicatoren per land",
    xaxis_title="Jaar",
    hovermode="x unified",
    legend=dict(
        orientation="v",
        yanchor="top",
        y=1,
        xanchor="left",
        x=1.05,
        bordercolor="Black",
        borderwidth=1
    ),
    updatemenus=[
        dict(
            buttons=dropdown_buttons,
            direction="down",
            pad={"r": 10, "t": 10},
            showactive=True,
            x=0.5,         
            xanchor="center",  
            y=1,            
            yanchor="top" 
        )
    ],
    height=400,
    width=1100  
)

fig.update_yaxes(title_text="Migranten (aantal)", secondary_y=False)
fig.update_yaxes(title_text="Indicatorwaarde", secondary_y=True)
for i, trace in enumerate(fig.data):
    fig.data[i].visible = "Puerto Rico" in traces[i]



fig.show()

Figuur 4: Een visualisatie van de top 20 landen met de meeste emigratie tov de bevolking samen met drie indicatoren die de leefomstandigheden samenvatten van een land (Zie legenda voor kleur aanduidingen). Het doel van de visualisatie is om de lezer interactief te tonen dat ieder land niet per se een directe connectie heeft tussen migratie en slechte leefomstandigheden en dus deels het tegendeel wordt bewezen van ons perspectief.

Uit de visualisatie hierboven aangegeven kunnen we een paar conclusies trekken. Allereerst zien we dat slechte levensomstandigheden niet altijd een garantie voor verhoging in migratiecijfers zijn, bij Puerto Rico zien we bijvoorbeeld dat het aantal migranten over de jaren heen wisselt samen met de cijfers van de gekozen indicatoren. Dit geeft wel aan dat er een verband is tussen migratie en de veranderingen in de leefomstandigheden en gezondheid van mensen, maar dat heeft niet altijd een stijging van migratie als gevolg.

Uit sommige specifieke gevallen zoals Mexico eerder gegeven is deze conclusie wel te trekken. Een ander specifiek geval waar deze conclusie is te trekken is Ierland, dit land heeft een massale toename in migratie tussen de jaren 1960-1970. Deze massale toename in migratie is net zoals bij Mexico een historische gebeurtenis verbonden, tijdens deze periode heeft zich “The Troubles” afgespeeld in Noord-Ierland waar conflict en onrust het thema was in deze periode(Gilmartin, 2022). Deze historische evenementen die een slechte leefomstandigheid vormen voor de burger van zowel Mexico als Ierland laat zien dat slechte levensomstandigheden wel degelijk uitmaken voor een toename in migratie wereldwijd maar de visualisatie geeft ook het tegendeel van ons perspectief aan namelijk dat slechte leefomstandigheden niet de centrale reden is voor massale migratie wereldwijd.

Perspectief twee#

Eerste argument: Mortality Rate en Migratie#

Om het verband tussen levensomstandigheden en migratie verder te onderzoeken, hebben we gekeken naar de mortality rate (sterftecijfers onder de 5 jaar per 1.000 levendgeborenen). Deze indicator geeft een duidelijk beeld van de kwaliteit van gezondheidszorg, voeding en algemene leefomstandigheden in een land. We hebben gekeken naar de cijfers tussen 1960 en 2000 op vijf verschillende momenten om betere conclusies te kunnen trekken en om de ontwikkeling in de landen aan te tonen. Het idee van deze visualisatie is om te laten zien in welke landen de levensomstandigheden het slechtst zijn en in welke landen mensen dus het minst graag zouden willen leven.

df = pd.read_excel('bbb.xlsx')
a = pd.read_excel('gpd per inwoner.xlsx')
df['2000_numeric'] = pd.to_numeric(df[2000], errors='coerce')

df_clean = df[df['2000_numeric'].notna()]

df_long = df.melt(id_vars=['Country Name', 'Country Code'],
                  value_vars=['1960 [YR1960]', '1970 [YR1970]', '1980 [YR1980]', '1990 [YR1990]', '2000_numeric'],
                  var_name='Year',
                  value_name='Value')

df_long['Value'] = pd.to_numeric(df_long['Value'], errors='coerce')

fig = px.choropleth(df_long,
                    locations='Country Code',
                    color='Value',
                    hover_name='Country Name',
                    animation_frame='Year',
                    projection='natural earth',
                    title='Mortality rate, under-5 (per 1,000 live births)',
                    color_continuous_scale='Viridis',
                    range_color=(0, 300),
                    height=600)

fig.show()

Figuur 5: Een wereldwijd overzicht van de Sterfecijfers van kinderen onder de leeftijd van 5 jaar door middel van een heatmap waarbij een lichtere kleur een hoger cijfer betekend. Deze visualisatie geeft de lezer inzicht in de slechte leefomstandigheid van sommige landen door sterfte cijfers van kinderen weer te geven wat een oorzak kan zijn van slechte gezondheids- en kinderzorg.

Een deel van de data ontbreekt jammer genoeg in de dataset (zeker in 1960), maar de visualisatie laat nog steeds duidelijk zien in welke gebieden van de wereld de levensomstandigheden slecht zijn. Zeker in Afrika, Zuid-Amerika en het zuiden van Azië zie je dat de mortality rate van mensen onder de vijf jaar veel hoger is dan in gebieden zoals Europa en Noord-Amerika. Hieruit zou je kunnen afleiden dat er veel meer mensen emigreren uit landen in Afrika dan uit landen in Europa. In Europa hebben namelijk alle landen een zeer lage en vergelijkbare value.

Emigratie in vergelijking met bevolking#

Om een beter inzicht te krijgen in de migratiestromen, hebben we gekeken naar het emigratiepercentage ten opzichte van de bevolkingsgrootte in een periode van decennia. Deze visualisatie toont aan dat landen met een donkerder rode kleur een hoger emigratiepercentage hebben, wat betekent dat een groter deel van hun bevolking het land verlaat. Het idee van deze visualisatie is om te laten zien uit welke landen een groter gedeelte van de mensen weg wil om aan te kunnen tonen in welke landen mensen het minst graag willen leven.

{
    "tags": [
        "hide_input",
    ]
}

migration_file = r"P_Data_Extract_From_Global_Bilateral_Migration.xlsx"
migration_df = pd.read_excel(migration_file)
population_file = r"P_Data_Extract_From_World_Development_Indicators (4).xlsx"
population_df = pd.read_excel(population_file, sheet_name='Data')
years = ['1960 [1960]', '1970 [1970]', '1980 [1980]', '1990 [1990]', '2000 [2000]']
for year_col in years:
    migration_df[year_col] = pd.to_numeric(migration_df[year_col], errors='coerce').fillna(0)


melted_df = migration_df.melt(id_vars=['Country Origin Name', 'Country Origin Code', 
                                      'Country Dest Name', 'Country Dest Code'],
                             value_vars=years,
                             var_name='Year',
                             value_name='Migrants')


melted_df['Year'] = melted_df['Year'].str.extract(r'(\d+)').astype(int)
population_df = population_df[population_df['Series Code'] == 'SP.POP.TOTL']
population_melted = population_df.melt(id_vars=['Country Name', 'Country Code'],
                                      value_vars=['1960 [YR1960]', '1970 [YR1970]', 
                                                 '1980 [YR1980]', '1990 [YR1990]', 
                                                 '2000 [YR2000]'],
                                      var_name='Year',
                                      value_name='Population')

population_melted['Year'] = population_melted['Year'].str.extract(r'(\d+)').astype(int)


population_melted['Population'] = pd.to_numeric(population_melted['Population'], errors='coerce')


outgoing = melted_df.groupby(['Country Origin Name', 'Country Origin Code', 'Year'], 
                           as_index=False)['Migrants'].sum()
outgoing = outgoing.rename(columns={'Country Origin Name': 'Country', 
                                  'Country Origin Code': 'Code', 
                                  'Migrants': 'Outgoing'})

outgoing = outgoing.merge(population_melted, 
                         left_on=['Code', 'Year'], 
                         right_on=['Country Code', 'Year'],
                         how='left')

outgoing['Emigration Percentage'] = (outgoing['Outgoing'] / outgoing['Population']) * 100

outgoing = outgoing.dropna(subset=['Population'])

outgoing['Hover Text'] = outgoing.apply(
    lambda x: f"<b>{x['Country']}</b><br>" +
              f"Jaar: {x['Year']}<br>" +
              f"Emigranten: {int(x['Outgoing']):,}<br>" +
              f"Bevolking: {int(x['Population']):,}<br>" +
              f"Emigratiepercentage: {x['Emigration Percentage']:.2f}%",
    axis=1
)

current_year = outgoing['Year'].min()
df_year = outgoing[outgoing['Year'] == current_year]

max_percentage = df_year['Emigration Percentage'].max()

fig = px.choropleth(df_year, 
                    locations="Code",
                    color="Emigration Percentage",
                    hover_name="Hover Text",
                    color_continuous_scale=px.colors.sequential.Reds,
                    range_color=[0, 50],
                    title=f"Emigratie als Percentage van de Bevolking ({current_year})",
                    labels={'Emigration Percentage': 'Emigratie (%)'})

fig.update_layout(
    annotations=[
        dict(
            x=0.5,
            y=-0.1,
            xref='paper',
            yref='paper',
            text="<b>Kleurverklaring:</b> Donkerder rood = hoger emigratiepercentage (meer emigratie ten opzichte van bevolkingsgrootte)",
            showarrow=False,
            font=dict(size=12))
    ],
    margin=dict(b=100)
)

buttons = []
for year in sorted(outgoing['Year'].unique()):
    df_year = outgoing[outgoing['Year'] == year]
    max_percentage = df_year['Emigration Percentage'].max()
    buttons.append(
        dict(
            label=str(year),
            method="update",
            args=[{"z": [df_year['Emigration Percentage'].tolist()],
                  "hovertext": [df_year['Hover Text'].tolist()],
                  "title": f"Emigratie als Percentage van de Bevolking",
                  "range_color": [0, max_percentage]}
            ]
        )
    )

fig.update_layout(
    updatemenus=[{
        "buttons": buttons,
        "direction": "down",
        "showactive": True,
        "x": 0.1,
        "xanchor": "left",
        "y": 1.15,
        "yanchor": "top"
    }],
    coloraxis_colorbar=dict(
        title="Emigratie (%)",
        ticks="outside"
    ),
    height=400
)

fig.show()

Figuur 6: Een wereldwijde visualisatie van wereldwijde emigratie maar dan met de migratie t.o.v de totale bevolking. De lezer kan hieruit de plekken aanwijzen met de meeste migratie wat inzicht toont met de beargumentatie verder gegeven.

Uit deze visualisatie kun je zien dat er best wel veel landen zijn waar mensen uit willen emigreren, maar dat dit redelijk verdeeld is over de wereld. Het is niet zo dat verschillende continenten ongeveer dezelfde kleur hebben. Dit is verbazingwekkend, omdat dit wel zo was bij de mortality rate-visualisatie. Het tweede ding dat heel erg opvalt, is dat de landen met een hoge mortality rate niet echt overeenkomen met de landen waar veel mensen uit emigreren. Landen in Oost-Europa waar de mortality rate best zeer laag is vergeleken met de rest van de wereld, hebben nog steeds een heel erg groot emigratiepercentage. Er zijn ook landen met een hogere mortality rate waar veel mensen uit emigreren, maar het is zo dat de landen met de hoogste mortality rate onder vijf jaar, dus landen met heel slechte levensomstandigheden, landen zijn waar het emigratiepercentage laag is. Hieruit kan je afleiden dat er niet echt een duidelijke vergelijking is tussen mortality rate en emigratiepercentage.

Tweede argument: gemiddeld BBP per persoon en emigratiepercentage trendline#

Een tweede manier om naar de levensomstandigheden in een land te kijken is door te kijken naar hoe economisch succesvol een land is. Daarom hebben we gekeken naar het gemiddelde BBP per persoon van alle landen. Als het gemiddelde BBP per persoon in landen hoger zou zijn, zou je zeggen dat het beter gaat met de mensen. Mensen zouden makkelijker aan eten moeten komen, er is meer werk en de zorg hoort beter te zijn. De volgende visualisatie linkt gemiddeld BBP per persoon aan emigratiepercentage om te kijken of er een verband is tussen deze twee variabelen.

aa = pd.read_excel('bbb.xlsx')
a = pd.read_excel('gpd per inwoner.xlsx')
df_filtered = outgoing[outgoing['Year'] == 2000]
b = a.rename(columns={'Country Name': 'Country'})
cc = pd.read_csv("https://ourworldindata.org/grapher/continents-according-to-our-world-in-data.csv?v=1&csvType=full&useColumnShortNames=true", storage_options = {'User-Agent': 'Our World In Data data fetch/1.0'})
c = cc.rename(columns={'Entity': 'Country'})
bb = b.rename(columns={2000: 'BBP per persoon'})
aaa = pd.merge(df_filtered, bb, on='Country')
aaaa = pd.merge(aaa, c, on='Country')
aaaa.head(n=10)
df_wereld = aaaa
df_europa = aaaa[aaaa['owid_region'] == 'Europe']

fig_europa = px.scatter(
    df_europa,
    x='Emigration Percentage',
    y='BBP per persoon',
    color='Emigration Percentage',
    size='Population',
    hover_name='Country',
    trendline="ols",
    color_continuous_scale='Plasma'
)

fig_wereld = px.scatter(
    df_wereld,
    x='Emigration Percentage',
    y='BBP per persoon',
    color='Emigration Percentage',
    size='Population',
    hover_name='Country',
     trendline="ols",
    color_continuous_scale='Plasma'
)

fig = go.Figure(data=fig_europa.data + fig_wereld.data)
for i, trace in enumerate(fig.data):
    fig.data[i].visible = i < len(fig_europa.data)



fig.update_coloraxes(showscale=False)

fig.update_traces(
    marker=dict(opacity=0.8, line=dict(width=0.5, color='DarkSlateGrey'))
)

fig.update_layout(
    updatemenus=[
        dict(
            type="dropdown",
            direction="down",
            x=0.5,
            xanchor="center",
            y=1.15,
            yanchor="top",
            showactive=True,
            buttons=[
                dict(label="Europa",
                     method="update",
                     args=[
                         {"visible": [True]*len(fig_europa.data) + [False]*len(fig_wereld.data)},
                         {"title": "Europa: BBP per persoon vs Emigratiepercentage"}
                     ]),
                dict(label="Alle landen",
                     method="update",
                     args=[
                         {"visible": [False]*len(fig_europa.data) + [True]*len(fig_wereld.data)},
                         {"title": "Wereld: BBP per persoon vs Emigratiepercentage"}
                     ])
            ]
        )
    ],
    title="Europa: BBP per persoon vs Emigratiepercentage",
    plot_bgcolor='white',
    xaxis_title='Emigratiepercentage (%)',
    yaxis_title='BBP per persoon ($)',
    font=dict(family='Arial', size=14),
    title_font=dict(size=18),
    xaxis=dict(showgrid=True, gridcolor='lightgray'),
    yaxis=dict(showgrid=True, gridcolor='lightgray')
)
fig.show()

Figuur 7: Een visualisatie waarbij de BBP per persoon wordt vergeleken met het percentage emigratie. Een trendlijn is gegeven voor het trekken van een conclusie.

In de visualisatie hierboven zien we het gemiddeld BBP per persoon in een land gelinkt aan het emigratiepercentage in een land in 2000. Je kan hier de informatie zien van de landen in Europa en van alle landen op de wereld. In Europa is het duidelijk te zien met de trendline dat als het gemiddelde BBP per persoon in een land hoger is, het emigratiepercentage lager is. Hieruit zou je kunnen concluderen dat mensen liever weg willen uit landen waar het slecht gaat dan uit landen waar het goed gaat. Maar als je naar de scatterplot van de wereld kijkt, zie je een ander resultaat. Op de scatterplot met alle landen van de wereld is de trendline bijna niet dalend, maar blijft deze redelijk stabiel. Veel landen met een laag gemiddeld BBP per persoon hebben ook een laag emigratiepercentage, terwijl dit in Europa veel minder is.

Europa is een continent waar het verschil tussen landen die dicht bij elkaar liggen procentueel gezien redelijk groot is en dit is in de rest van de wereld duidelijk minder. Dit zou de reden kunnen zijn dat er in Europa een duidelijk verband is tussen gemiddeld BBP per persoon en emigratiepercentage in de landen. Omdat dit verband er niet is op de hele wereld, kan je hieruit afleiden dat migratie niet per se te maken heeft met hoe slecht het met een land gaat, maar eerder met hoe goed het met de buurlanden gaat.

Derde argument: buurlandverschillen#

Naast het emigratiepercentage hebben we ook de netto-migratie per land geanalyseerd. Netto-migratie geeft het verschil aan tussen het aantal immigranten en emigranten. Landen met een positieve netto-migratie (meer immigranten dan emigranten) zijn vaak economisch stabiel en bieden betere voorzieningen, terwijl landen met een negatieve netto-migratie te maken hebben met een vertrekkende bevolking. Deze visualisatie hebben we vooral om te kijken naar welke landen mensen echt graag in willen wonen en in welke landen mensen niet graag willen wonen.

file2 = r"P_Data_Extract_From_Global_Bilateral_Migration.xlsx"
df = pd.read_excel(file2)


years = ['1960 [1960]', '1970 [1970]', '1980 [1980]', '1990 [1990]', '2000 [2000]']


for year_col in years:
    df[year_col] = pd.to_numeric(df[year_col], errors='coerce').fillna(0)


melted_df = df.melt(id_vars=['Country Origin Name', 'Country Origin Code', 
                            'Country Dest Name', 'Country Dest Code'],
                   value_vars=years,
                   var_name='Year',
                   value_name='Migrants')

melted_df['Year'] = melted_df['Year'].str.extract(r'(\d+)').astype(int)


incoming = melted_df.groupby(['Country Dest Name', 'Country Dest Code', 'Year'], as_index=False)['Migrants'].sum()
outgoing = melted_df.groupby(['Country Origin Name', 'Country Origin Code', 'Year'], as_index=False)['Migrants'].sum()
incoming = incoming.rename(columns={'Country Dest Name': 'Country', 'Country Dest Code': 'Code', 'Migrants': 'Incoming'})
outgoing = outgoing.rename(columns={'Country Origin Name': 'Country', 'Country Origin Code': 'Code', 'Migrants': 'Outgoing'})
net_migration = incoming.merge(outgoing, on=['Country', 'Code', 'Year'], how='outer')
net_migration = net_migration.fillna(0)
net_migration['Net Migration'] = net_migration['Incoming'] - net_migration['Outgoing']
net_migration['Hover Text'] = net_migration.apply(
    lambda x: f"<b>{x['Country']}</b><br>" +
              f"Incoming: {int(x['Incoming']):,}<br>" +
              f"Outgoing: {int(x['Outgoing']):,}<br>" +
              f"Net Migration: {int(x['Net Migration']):,}",
    axis=1
)
current_year = net_migration['Year'].min()
df_year = net_migration[net_migration['Year'] == current_year]
max_migration = max(abs(df_year['Net Migration']))

fig = px.choropleth(df_year, 
                    locations="Code",
                    color="Net Migration",
                    hover_name="Hover Text",
                    color_continuous_scale=px.colors.diverging.RdBu,
                    range_color=[-max_migration, max_migration],
                    title=f"Global Migration",
                    labels={'Net Migration': 'Net Migration'})

fig.update_layout(
    annotations=[
        dict(
            x=0.5,
            y=-0.1,
            xref='paper',
            yref='paper',
            text="<b>Color Explanation:</b> Blauw = Positieve netto migratie (meer inkomend dan uitgaand), Rood = Negatieve netto migratie (meer uitgaand dan inkomend)",
            showarrow=False,
            font=dict(size=12))
    ],
    margin=dict(b=100)
)

buttons = []
for year in sorted(net_migration['Year'].unique()):
    df_year = net_migration[net_migration['Year'] == year]
    buttons.append(
        dict(
            label=str(year),
            method="update",
            args=[{"z": [df_year['Net Migration'].tolist()],
                  "hovertext": [df_year['Hover Text'].tolist()],
                  "title": f"Globale Migratie"}
            ]
        )
    )


fig.update_layout(
    updatemenus=[{
        "buttons": buttons,
        "direction": "down",
        "showactive": True,
        "x": 0.1,
        "xanchor": "left",
        "y": 1.15,
        "yanchor": "top"
    }],
    coloraxis_colorbar=dict(
        title="Net Migration",
        ticks="outside"
    ),
    height=500
)

fig.show()

Figuur 8: Een wereldwijde visualisatie waarbij wordt getoond dat er een verschil is tussen landen met de vorige wereldwijde visualisaties op basis van netto emigratie/immigratie.

In deze visualisatie wordt aangetoond dat West-Europese landen en de VS een zeer positieve net migration hebben, maar er vallen ook een paar andere dingen op. Het eerste wat opvalt, is dat de meeste landen die een hoge mortality rate onder vijf jaar en een laag gemiddeld BBP per persoon hebben geen lage net migration hebben. Het tweede wat opvalt, is het buurlandverschil. Naast een paar landen met heel erg veel inwoners die dus minder effectief zijn op deze schaal, zie je vaak de grootste kleurverschillen tussen buurlanden. Duitsland-Polen en VS-Mexico zijn hiervan twee goede voorbeelden. Dit zijn vaak ook buurlanden waar het verschil tussen de levensomstandigheden best wel groot is. Dit laat zien dat mensen vaak migreren naar buurlanden omdat de levensomstandigheden daar beter zijn dan in hun eigen land, in plaats van emigreren uit landen waar de levensomstandigheden echt heel slecht zijn.

Reflectie#

Voor deze opdracht hebben we in een groep gewerkt aan het maken van visuele data. De meeste mensen hebben actief samengewerkt, maar één groepsgenoot was onberijkbaar en hebben we geen contact mee gehad.

In het begin van de opdracht hebben we de taken goed verdeeld en hadden we goed contact met elkaar om understeuning te kunnen vragen. Alle actieve groepsgenoten deden het werk dat ze verdeelt hadden gekregen en zelfs buiten het aangewezen werk werden er verschillende visualisaties gemaakt om te kijken of het beter paste, of omdat ze het leuk vonden. Dit zorgde ervoor dat de vaardigheid van de groepsgenoten op hoog niveau lag.

We hebben in dit project een grote hoeveelheid kennis opgedaan. We zijn erin geslaagd om jupyter notebook op een correcte manier te kunnen gebruiken en de visualisaties te maken met plotly. We hebben het voor elkaar gekregen om een groot deel van de visualisaties “interactive” te maken, al kwam dat soms met erg veel moeite.

Ook hebben we geleerd hoe we grafieken goed leesbaar moeten maken. Als een grafiek erg dicht op elkaar zat hebben we verschillende kleuren gebruikt om verschil aan te geven. Dit hebben we expres niet gedaan met een anti kleurenblindheids waardes die met plotly komen, omdat die erg afleidend fel zijn, maar met eigen kleuren die verschillend zijn.

Voor het feedbackmoment van onze TA hadden we nog niet echt een datastory. Dit komt omdat we in het begin echt vooral aan het focussen waren op data visualiseren. Hierdoor was ons verhaal nog redelijk onduidelijk en hadden we best wel kritische feedback gekregen. We waren het eens met veel van de feedback en hebben hierna ook nog veel aanpassingen gedaan op basis van de feedback. We hadden bijvoorbeeld onze twee perspectieven nog een beetje aangepast omdat er nog te veel onvereenkomst was met onze perspectieven. Hierdoor hadden wij ook onze argumenten en sommige visualisaties aangepast.

Werkverdeling#

De werkverdeling is op een goede manier gegaan. We hadden allemaal eigen ideeën over wat we gingen doen, dus kreeg iedereen in de eerste weken vrijheid om wat te proberen. Vanaf de derde week begonnen we te kijken naar wat we hadden en hoe we dat het beste konden samenvoegen. Voor elke visualisatie moest het persoon die het had gemaakt er zelf informatie bijschrijven over wat er werd afgebeeld en hoe dat bereikt was met python code. We hadden hier redelijk veel visualisaties en keken hier vooral naar welke visualisaties het beste zouden passen bij onze perspectieven die we redelijk laat ook nog een keer een beetje hadden veranderd om het duidelijker te maken. Het is niet zo dat we allemaal aan apparte dingen hebben gewerkt. In plaats daarvan heeft iedereen een beidrage toegevoegd aan elk deel van de datastory waardoor we niet echt duidelijk kunnen zeggen wie wat heeft gedaan.

Bronnen:#

Solano, P., & Massey, D. S. (2022). Migrating through the Corridor of Death: The Making of a Complex Humanitarian Crisis. Journal on Migration and Human Security, 10(3), 147-172. https://doi.org/10.1177/23315024221119784 (Original work published 2022)

Gilmartin, N. (2022). Fear, force, and flight: configurations of intimidation and displacement in Northern Ireland’s ‘Troubles.’ Journal of Ethnic and Migration Studies, 48(17), 4277–4294. https://doi.org/10.1080/1369183X.2022.2052031